package com.managertrade.job;

import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.managertrade.dao.sqlite.entity.KlineWithIndicatorsEntity;
import com.managertrade.dao.sqlite.entity.StrategyConfig;
import com.managertrade.dao.sqlite.entity.StrategyTrade;
import com.managertrade.service.impl.StrategyConfigService;
import com.managertrade.service.impl.StrategyTradeService;
import com.managertrade.service.sqllite.service.KlineWithIndicatorsService;
import com.managertrade.util.BackpackApiClientRequest;
import com.managertrade.util.strategy.client.BackpackTradingBot;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class StrategyScheduler {

    @Autowired
    StrategyConfigService strategyConfigService;
    @Autowired
    StrategyTradeService strategyTradeService;
    @Autowired
    KlineWithIndicatorsService klineWithIndicatorsService;
    @Autowired
    private ObjectMapper mapper;

    /**
     * 每 30 秒执行一次定时任务
     */
    @Scheduled(fixedDelay = 1000 * 60 * 10)
    @Transactional
    public void executeStrategies() {
        log.info("=== 定时任务执行：检查策略状态 ===");

        // 读取所有未过期的策略
        List<StrategyConfig> strategies = strategyConfigService.list();

        for (StrategyConfig example : strategies) {
            if (!example.getIsActive() ) {
                return;
            }

            try {
                if(!example.getAutoUpdate()){
                     processFixStrategy(example);
                    return;
                }
                processStrategy(example); // 核心处理逻辑
            } catch (Exception ex) {
                log.error("策略执行失败 id={} name={} error={}", example.getId(), example.getStrategyName(), ex.getMessage());
            }
        }
    }

    private void processFixStrategy(StrategyConfig s) throws Exception {
        String backPackSymbol = getbackPackSymbol(s.getSymbol());
        String binanceSymbol = s.getSymbol();
        BigDecimal price = fetchLatestPrice(binanceSymbol);
        if (price == null) {
            log.info("未获取到价格");
            return;
        }

        // ===== 计算区间 =====
        BigDecimal high = s.getHighPrice();
        BigDecimal low = s.getLowPrice();
        BigDecimal mid = low.add(high).divide(BigDecimal.valueOf(2), 8, RoundingMode.HALF_UP);

        // ===== 获取未平仓记录 =====
        StrategyTrade openTrade = strategyTradeService.findByStrategyId(s.getId()).stream()
                .filter(t -> t.getSellOrderId() == null)
                .max(Comparator.comparing(StrategyTrade::getTradeTime))
                .orElse(null);

        // ===== 判断市场方向 =====
        String marketDirection = calcTwoDirection(price,low,high);

        // ================================
        //        ① 无持仓 → 开仓
        // ================================
        if (openTrade == null ) {
            if(marketDirection!=null){
                log.info("策略 [{}] 当前价格 {} 区间: [{}, {}, {}] 方向 {}",
                        s.getStrategyName(), price, low, mid, high, marketDirection);

                StrategyTrade newTrade = new StrategyTrade();
                newTrade.setStrategyId(s.getId());
                newTrade.setDirection(marketDirection);
                newTrade.setQuantity(s.getQuantity());
                newTrade.setClientBuyId(String.valueOf(generateClientId()));
                newTrade.setTradeTime(DateUtil.now());

                BackpackTradingBot.OrderResult result = placeOrder(s, marketDirection, price, backPackSymbol);
                if (result == null) {
                    log.info("策略 [{}] 开仓失败 direction={}", s.getStrategyName(), marketDirection);
                    return;
                }

                newTrade.setBuyOrderId(result.getId());

                BackpackTradingBot.BackpackPosition pos = getCurrentPosition(backPackSymbol,s);
                if (pos != null) {
                    newTrade.setBuyPrice(new BigDecimal(pos.getEntryPrice()));
                }

                strategyTradeService.save(newTrade);
                log.info("策略 [{}] 开仓成功 {}", s.getStrategyName(), marketDirection);
                return;
            }else{
                return;
            }

        }

        // ================================
        //        ② 有持仓 → 方向相反？
        // ================================
        String currentDirection = openTrade.getDirection();

        if (!marketDirection.equals(currentDirection)) {

            log.info("策略 [{}] 方向反转 {} -> {} 触发反向开仓",
                    s.getStrategyName(), currentDirection, marketDirection);

            // ===== (1) 平掉当前仓位 =====
            String closeType = currentDirection.equals("buy") ? "sell" : "buy";

            BackpackTradingBot.OrderResult closeResult = placeOrder(s, closeType, price, backPackSymbol);

            if (closeResult != null) {
                openTrade.setClientSellId(String.valueOf(generateClientId()));
                openTrade.setSellOrderId(closeResult.getId());
                openTrade.setCloseDirection(currentDirection.equals("buy") ? "CLOSE_LONG" : "CLOSE_SHORT");
                strategyTradeService.save(openTrade);
            }

            // ===== (2) 反向开仓 =====
            StrategyTrade reversedTrade = new StrategyTrade();
            reversedTrade.setStrategyId(s.getId());
            reversedTrade.setDirection(marketDirection);
            reversedTrade.setQuantity(s.getQuantity());
            reversedTrade.setClientBuyId(String.valueOf(generateClientId()));
            reversedTrade.setTradeTime(DateUtil.now());

            BackpackTradingBot.OrderResult reverseOpen = placeOrder(s, marketDirection, price, backPackSymbol);

            if (reverseOpen != null) {
                reversedTrade.setBuyOrderId(reverseOpen.getId());

                BackpackTradingBot.BackpackPosition newPos = getCurrentPosition(backPackSymbol,s);
                if (newPos != null) {
                    reversedTrade.setBuyPrice(new BigDecimal(newPos.getEntryPrice()));
                }
                strategyTradeService.save(reversedTrade);
            }

            return;
        }


        // ================================
        //        ③ 有持仓 → 判断平仓信号
        // ================================

        BackpackTradingBot.BackpackPosition currentPos = getCurrentPosition(backPackSymbol,s);
        if (currentPos == null) {
            openTrade.setSellOrderId("0"); // 强制关闭
            strategyTradeService.save(openTrade);
            return;
        }

        // 止盈止损计算
        BigDecimal takeProfitPrice = openTrade.getBuyPrice()
                .multiply(BigDecimal.ONE.add(s.getProfitPercent().divide(BigDecimal.valueOf(100))));

        BigDecimal stopLossPrice = openTrade.getBuyPrice()
                .multiply(BigDecimal.ONE.subtract(s.getStopLossPercent().divide(BigDecimal.valueOf(100))));

        boolean closeFlag = false;

        // 止盈
        if ((currentDirection.equals("buy") && price.compareTo(takeProfitPrice) >= 0) ||
                (currentDirection.equals("sell") && price.compareTo(takeProfitPrice) <= 0)) {

            closeFlag = true;
            openTrade.setCloseDirection(currentDirection.equals("buy") ? "CLOSE_LONG" : "CLOSE_SHORT");
            log.info("策略 [{}] 达到止盈", s.getStrategyName());
        }

        // 止损
        else if ((currentDirection.equals("buy") && price.compareTo(stopLossPrice) <= 0) ||
                (currentDirection.equals("sell") && price.compareTo(stopLossPrice) >= 0)) {

            closeFlag = true;
            openTrade.setCloseDirection(currentDirection.equals("buy") ? "CLOSE_LONG" : "CLOSE_SHORT");
            log.info("策略 [{}] 触发止损", s.getStrategyName());
        }

        // 触及区间边界
        else if ((currentDirection.equals("buy") && price.compareTo(high) >= 0) ||
                (currentDirection.equals("sell") && price.compareTo(low) <= 0)) {

            closeFlag = false;
            openTrade.setCloseDirection(currentDirection.equals("buy") ? "CLOSE_LONG" : "CLOSE_SHORT");
            log.info("策略 [{}] 触发区间平仓", s.getStrategyName());
        }

        // ===== 执行平仓 =====
        if (closeFlag) {
            String orderType = currentDirection.equals("buy") ? "sell" : "buy";
            BackpackTradingBot.OrderResult closeResult = placeOrder(s, orderType, price, backPackSymbol);

            if (closeResult != null) {
                openTrade.setClientSellId(String.valueOf(generateClientId()));
                openTrade.setSellOrderId(closeResult.getId());
                strategyTradeService.save(openTrade);
            }
        }
    }

    public String getbackPackSymbol(String symbol){
        String usdt = symbol.substring(0, symbol.indexOf("USDT"));
        return usdt+"_USDC_PERP";

    }
    /**
     * 处理每一个策略
     */
    private void processStrategy(StrategyConfig s) throws Exception {

        String backPackSymbol = getbackPackSymbol(s.getSymbol());
        String binanceSymbol = s.getSymbol();
        BigDecimal price = fetchLatestPrice(binanceSymbol);
        if (price == null) {
            log.info("未获取到价格");
            return;
        }

        // ===== 计算区间 =====
        BigDecimal high = s.getHighPrice();
        BigDecimal low = s.getLowPrice();
        BigDecimal mid = low.add(high).divide(BigDecimal.valueOf(2), 8, RoundingMode.HALF_UP);

        // ===== 获取未平仓记录 =====
        StrategyTrade openTrade = strategyTradeService.findByStrategyId(s.getId()).stream()
                .filter(t -> t.getSellOrderId() == null)
                .max(Comparator.comparing(StrategyTrade::getTradeTime))
                .orElse(null);

        // ===== 判断市场方向 =====
        String marketDirection = calcDirection(price,low,mid,high);

        // ================================
        //        ① 无持仓 → 开仓
        // ================================
        if (openTrade == null) {

            log.info("策略 [{}] 当前价格 {} 区间: [{}, {}, {}] 方向 {}",
                    s.getStrategyName(), price, low, mid, high, marketDirection);

            StrategyTrade newTrade = new StrategyTrade();
            newTrade.setStrategyId(s.getId());
            newTrade.setDirection(marketDirection);
            newTrade.setQuantity(s.getQuantity());
            newTrade.setClientBuyId(String.valueOf(generateClientId()));
            newTrade.setTradeTime(DateUtil.now());

            BackpackTradingBot.OrderResult result = placeOrder(s, marketDirection, price, backPackSymbol);
            if (result == null) {
                log.info("策略 [{}] 开仓失败 direction={}", s.getStrategyName(), marketDirection);
                return;
            }

            newTrade.setBuyOrderId(result.getId());

            BackpackTradingBot.BackpackPosition pos = getCurrentPosition(backPackSymbol,s);
            if (pos != null) {
                newTrade.setBuyPrice(new BigDecimal(pos.getEntryPrice()));
            }

            strategyTradeService.save(newTrade);
            log.info("策略 [{}] 开仓成功 {}", s.getStrategyName(), marketDirection);
            return;
        }

        // ================================
        //        ② 有持仓 → 方向相反？
        // ================================
        String currentDirection = openTrade.getDirection();

        if (!marketDirection.equals(currentDirection)) {

            log.info("策略 [{}] 方向反转 {} -> {} 触发反向开仓",
                    s.getStrategyName(), currentDirection, marketDirection);

            // ===== (1) 平掉当前仓位 =====
            String closeType = currentDirection.equals("buy") ? "sell" : "buy";

            BackpackTradingBot.OrderResult closeResult = placeOrder(s, closeType, price, backPackSymbol);

            if (closeResult != null) {
                openTrade.setClientSellId(String.valueOf(generateClientId()));
                openTrade.setSellOrderId(closeResult.getId());
                openTrade.setCloseDirection(currentDirection.equals("buy") ? "CLOSE_LONG" : "CLOSE_SHORT");
                strategyTradeService.save(openTrade);
            }

            // ===== (2) 反向开仓 =====
            StrategyTrade reversedTrade = new StrategyTrade();
            reversedTrade.setStrategyId(s.getId());
            reversedTrade.setDirection(marketDirection);
            reversedTrade.setQuantity(s.getQuantity());
            reversedTrade.setClientBuyId(String.valueOf(generateClientId()));
            reversedTrade.setTradeTime(DateUtil.now());

            BackpackTradingBot.OrderResult reverseOpen = placeOrder(s, marketDirection, price, backPackSymbol);

            if (reverseOpen != null) {
                reversedTrade.setBuyOrderId(reverseOpen.getId());

                BackpackTradingBot.BackpackPosition newPos = getCurrentPosition(backPackSymbol,s);
                if (newPos != null) {
                    reversedTrade.setBuyPrice(new BigDecimal(newPos.getEntryPrice()));
                }
                strategyTradeService.save(reversedTrade);
            }

            return;
        }


        // ================================
        //        ③ 有持仓 → 判断平仓信号
        // ================================

        BackpackTradingBot.BackpackPosition currentPos = getCurrentPosition(backPackSymbol,s);
        if (currentPos == null) {
            openTrade.setSellOrderId("0"); // 强制关闭
            strategyTradeService.save(openTrade);
            return;
        }

        // 止盈止损计算
        BigDecimal takeProfitPrice = openTrade.getBuyPrice()
                .multiply(BigDecimal.ONE.add(s.getProfitPercent().divide(BigDecimal.valueOf(100))));

        BigDecimal stopLossPrice = openTrade.getBuyPrice()
                .multiply(BigDecimal.ONE.subtract(s.getStopLossPercent().divide(BigDecimal.valueOf(100))));

        boolean closeFlag = false;

        // 止盈
        if ((currentDirection.equals("buy") && price.compareTo(takeProfitPrice) >= 0) ||
                (currentDirection.equals("sell") && price.compareTo(takeProfitPrice) <= 0)) {

            closeFlag = true;
            openTrade.setCloseDirection(currentDirection.equals("buy") ? "CLOSE_LONG" : "CLOSE_SHORT");
            log.info("策略 [{}] 达到止盈", s.getStrategyName());
        }

        // 止损
        else if ((currentDirection.equals("buy") && price.compareTo(stopLossPrice) <= 0) ||
                (currentDirection.equals("sell") && price.compareTo(stopLossPrice) >= 0)) {

            closeFlag = true;
            openTrade.setCloseDirection(currentDirection.equals("buy") ? "CLOSE_LONG" : "CLOSE_SHORT");
            log.info("策略 [{}] 触发止损", s.getStrategyName());
        }

        // 触及区间边界
        else if ((currentDirection.equals("buy") && price.compareTo(high) <= 0) ||
                (currentDirection.equals("sell") && price.compareTo(low) >= 0)) {

            closeFlag = false;
            openTrade.setCloseDirection(currentDirection.equals("buy") ? "CLOSE_LONG" : "CLOSE_SHORT");
            log.info("策略 [{}] 触发区间平仓", s.getStrategyName());
        }

        // ===== 执行平仓 =====
        if (closeFlag) {
            String orderType = currentDirection.equals("buy") ? "sell" : "buy";
            BackpackTradingBot.OrderResult closeResult = placeOrder(s, orderType, price, backPackSymbol);

            if (closeResult != null) {
                openTrade.setClientSellId(String.valueOf(generateClientId()));
                openTrade.setSellOrderId(closeResult.getId());
                strategyTradeService.save(openTrade);
            }
        }
    }

    /** 计算6区间方向 */
    private String calcTwoDirection(BigDecimal price, BigDecimal low, BigDecimal high) {


        // 区域 1（高点之上）
        if (price.compareTo(high) > 0) {
            return "buy";  // ↑ 你可以换成 buy
        }

        // 区域 6（跌破 low）
        if (price.compareTo(low) <= 0) {
            return "sell";
        }

        return null; // 不可能出现
    }
    /** 计算6区间方向 */
    private String calcDirection(BigDecimal price, BigDecimal low, BigDecimal mid, BigDecimal high) {

        BigDecimal midLow = low.add(mid).divide(BigDecimal.valueOf(2), 8, RoundingMode.HALF_UP);
        BigDecimal midHigh = mid.add(high).divide(BigDecimal.valueOf(2), 8, RoundingMode.HALF_UP);

        // 区域 1（高点之上）
        if (price.compareTo(high) > 0) {
            return "buy";  // ↑ 你可以换成 buy
        }

        // 区域 2（midHigh ~ high）
        if (price.compareTo(midHigh) > 0 && price.compareTo(high) <= 0) {
            return "sell";
        }

        // 区域 3（mid ~ midHigh）
        if (price.compareTo(mid) > 0 && price.compareTo(midHigh) <= 0) {
            return "buy";
        }

        // 区域 4（midLow ~ mid）
        if (price.compareTo(midLow) > 0 && price.compareTo(mid) <= 0) {
            return "sell";
        }

        // 区域 5（low ~ midLow）
        if (price.compareTo(low) > 0 && price.compareTo(midLow) <= 0) {
            return "buy";
        }

        // 区域 6（跌破 low）
        if (price.compareTo(low) <= 0) {
            return "sell";
        }

        return null; // 不可能出现
    }


    // 每 5 秒执行一次，检查未平仓交易
    @Scheduled(fixedRate = 5000)
    public void processUnclosedTrades() {
        try {
            List<StrategyConfig> strategies = strategyConfigService.list();
            for(StrategyConfig strategyConfig :strategies){

                List<StrategyTrade> openTrades = strategyTradeService.findByStrategyIdAndProfitAmountIsNull(strategyConfig.getId());
                if (CollectionUtils.isEmpty(openTrades)) return;
                // 获取所有订单历史
                String result = BackpackApiClientRequest.getInstance(strategyConfig.getApiKey(), strategyConfig.getApiSecret()).orderHistoryQueryAll();
                List<BackpackApiClientRequest.OrderInfo> orderInfos = mapper.readValue(result,
                        new TypeReference<List<BackpackApiClientRequest.OrderInfo>>() {
                        });
                Map<String, BackpackApiClientRequest.OrderInfo> collect = orderInfos.stream()
                        .collect(Collectors.toMap(BackpackApiClientRequest.OrderInfo::getId, k -> k, (o1, o2) -> o2));


                for (StrategyTrade trade : openTrades) {
                    BackpackApiClientRequest.OrderInfo buyOrder = collect.get(trade.getBuyOrderId());
                    BackpackApiClientRequest.OrderInfo sellOrder = collect.get(trade.getSellOrderId());

                    if (buyOrder == null || sellOrder == null || !buyOrder.getStatus().equals("Filled") || !sellOrder.getStatus().equals("Filled"))continue; // 尚未成交


                    // 手续费比例 0.1%
                    BigDecimal feeRate = new BigDecimal("0.001");

                    // 计算开仓和平仓实际成交金额扣手续费
                    BigDecimal buyAmount = new BigDecimal(buyOrder.getExecutedQuoteQuantity()).multiply(feeRate);
                    BigDecimal sellAmount = new BigDecimal(sellOrder.getExecutedQuoteQuantity()).multiply(feeRate);

                    // 计算盈亏，依据开仓方向
                    BigDecimal profit;
                    if ("buy".equalsIgnoreCase(trade.getDirection())) {
                        profit = new BigDecimal(sellOrder.getExecutedQuoteQuantity())
                                .subtract(new BigDecimal(buyOrder.getExecutedQuoteQuantity()));
                        profit = profit.subtract(buyAmount);
                    } else { // SHORT
                        profit = new BigDecimal(buyOrder.getExecutedQuoteQuantity())
                                .subtract(new BigDecimal(sellOrder.getExecutedQuoteQuantity()));
                        profit = profit.subtract(sellAmount);
                    }

                    BigDecimal sellPrice = new BigDecimal(sellOrder.getExecutedQuoteQuantity())
                            .divide(new BigDecimal(sellOrder.getExecutedQuantity()), RoundingMode.HALF_UP);

                    trade.setProfitAmount(profit);
                    trade.setSellPrice(sellPrice);
                    trade.setTradeTime(DateUtil.now());
                    strategyTradeService.save(trade);

                    // 更新策略累计盈亏
                    StrategyConfig config = strategyConfigService.findById(trade.getStrategyId());
                    if (config != null) {
                        config.setTotalProfit(config.getTotalProfit() == null
                                ? profit
                                : config.getTotalProfit().add(profit));
                        strategyConfigService.save(config);
                    }
                    log.info("交易 [{}] 盈亏已更新: {}", trade.getId(), profit);
                }
            }

        } catch (Exception e) {
            log.error("未平仓交易盈亏处理失败", e);
        }
    }


    /**
     * 获取最新价格（你需要改成 OKX / Binance / 自己的数据源）
     */
    private BigDecimal fetchLatestPrice(String symbol) {
        KlineWithIndicatorsEntity topBySymbolAndPeriodOrderByTimestampDesc = klineWithIndicatorsService.findTopBySymbolAndPeriodOrderByTimestampDesc(symbol, "1m");
        if (topBySymbolAndPeriodOrderByTimestampDesc == null) {
            return null;
        }
        log.info("最新的行情数据时间：{} 价格：{}", topBySymbolAndPeriodOrderByTimestampDesc.getDatetime(), topBySymbolAndPeriodOrderByTimestampDesc.getClose());
        return BigDecimal.valueOf(topBySymbolAndPeriodOrderByTimestampDesc.getClose());
    }

    /**
     * 执行下单（ / 自有接口）
     */
    private BackpackTradingBot.OrderResult placeOrder(StrategyConfig s, String side, BigDecimal price, String symbol) {
        log.info("下单 symbol={} side={} type={} price={} quantity={}",
                s.getSymbol(), side, s.getOrderType(), price, s.getQuantity());
        BackpackTradingBot.OrderResult result = new BackpackTradingBot.OrderResult();
        try {
            List<Map<String, Object>> bodyList = new ArrayList<>();
            Map<String, Object> order = new HashMap<>();
            order.put("orderType", s.getOrderType());            // 市价开仓
            order.put("symbol", symbol);     // 交易对
            if ("buy".equalsIgnoreCase(side)) {
                // 买入（Bid）
                order.put("side", "Bid");
            } else {
                order.put("side", "Ask");
            }
            order.put("quantity", s.getQuantity());
            bodyList.add(order);
            String respText = BackpackApiClientRequest.getInstance(s.getApiKey(), s.getApiSecret()).post(bodyList);
            List<BackpackTradingBot.OrderResult> orders = mapper.readValue(respText, new TypeReference<List<BackpackTradingBot.OrderResult>>() {
            });
            result = orders.get(0);
        } catch (Exception e) {
            log.error("Open order error: " + e.getMessage());
            return null;
        }
        return result;
    }

    public long generateClientId() {
        // 当前毫秒时间戳的低 32 位
        return System.currentTimeMillis() & 0xFFFFFFFFL;
    }

    public BackpackTradingBot.BackpackPosition getCurrentPosition(String contractId,StrategyConfig s) throws Exception {
        String openOrders = BackpackApiClientRequest.getInstance(s.getApiKey(), s.getApiSecret()).getCurrentPosition(contractId);
        if (!StringUtils.isEmpty(openOrders)) {
            List<BackpackTradingBot.BackpackPosition> positions = mapper.readValue(openOrders, new TypeReference<List<BackpackTradingBot.BackpackPosition>>() {
            });
            if (!CollectionUtils.isEmpty(positions)) {
                return positions.get(0);
            }
        }
        return null;
    }

    @Scheduled(fixedRate = 10000)
    public  void calcDynamicRange() {
        //读取
        List<StrategyConfig> strategies = strategyConfigService.list();
        for(StrategyConfig config:strategies ){
            if(!config.getAutoUpdate()){
                return;
            }
            //设置最低和最高区间 // 最近 1400 根
            int size = 168;
            PageRequest pageRequest = PageRequest.of(0, size, Sort.by(Sort.Direction.DESC, "timestamp"));
            List<KlineWithIndicatorsEntity> latest1400 = klineWithIndicatorsService.findBySymbolAndPeriodPaged(config.getSymbol(), "1h", pageRequest);
            latest1400.sort(Comparator.comparing(KlineWithIndicatorsEntity::getTimestamp));
            Optional<Double> max = latest1400.stream().map(k -> k.getClose()).max(Comparator.naturalOrder());
            Optional<Double> min = latest1400.stream().map(k -> k.getClose()).min(Comparator.naturalOrder());
            if(max.isPresent()){
                BigDecimal bigDecimalMax = new BigDecimal(max.get());
                bigDecimalMax =bigDecimalMax.setScale(3,RoundingMode.HALF_UP);
                config.setHighPrice(bigDecimalMax);
            }
            if(min.isPresent()){
                BigDecimal bigDecimalMin = new BigDecimal(min.get());
                bigDecimalMin = bigDecimalMin.setScale(3,RoundingMode.HALF_UP);
                config.setLowPrice(bigDecimalMin);
            }
            log.info("更新最大值：{}和最小值配置：{}",config.getHighPrice(),config.getLowPrice());
            strategyConfigService.save(config);
            //最新价格
            KlineWithIndicatorsEntity topBySymbolAndPeriodOrderByTimestampDesc = klineWithIndicatorsService.findTopBySymbolAndPeriodOrderByTimestampDesc(config.getSymbol(), "1m");
            BigDecimal mid = config.getLowPrice().add(config.getHighPrice()).divide(BigDecimal.valueOf(2), 8, RoundingMode.HALF_UP);
            printRegionsWithCost(new BigDecimal(topBySymbolAndPeriodOrderByTimestampDesc.getClose()),config.getLowPrice(),mid,config.getHighPrice(),latest1400);
        }
    }

    /**
     * 根据价格判断属于哪一区域，并返回交易方向和区间编号
     *
     * @param price 当前价格
     * @param low   最低价
     * @param mid   中间价
     * @param high  最高价
     */
    public static Map<String, BigDecimal> printRegionsWithCost(BigDecimal price,
                                                               BigDecimal low,
                                                               BigDecimal mid,
                                                               BigDecimal high,
                                                               List<KlineWithIndicatorsEntity> klines) {

        BigDecimal midLow = low.add(mid).divide(BigDecimal.valueOf(2), 8, RoundingMode.HALF_UP);
        BigDecimal midHigh = mid.add(high).divide(BigDecimal.valueOf(2), 8, RoundingMode.HALF_UP);

        // 计算每个区间的成本
        Map<String, BigDecimal> costMap = new HashMap<>();
        Map<String, BigDecimal> volMap = new HashMap<>();
        for (int i = 1; i <= 6; i++) {
            costMap.put("区" + i, BigDecimal.ZERO);
            volMap.put("区" + i, BigDecimal.ZERO);
        }

        for (KlineWithIndicatorsEntity k : klines) {
            BigDecimal kPrice = BigDecimal.valueOf((k.getOpen() + k.getHigh() + k.getLow() + k.getClose()) / 4.0);
            BigDecimal volume = BigDecimal.valueOf(k.getVolume());

            int region;
            if (kPrice.compareTo(high) > 0) region = 1;
            else if (kPrice.compareTo(midHigh) > 0) region = 2;
            else if (kPrice.compareTo(mid) > 0) region = 3;
            else if (kPrice.compareTo(midLow) > 0) region = 4;
            else if (kPrice.compareTo(low) > 0) region = 5;
            else region = 6;

            costMap.put("区" + region, costMap.get("区" + region).add(kPrice.multiply(volume)));
            volMap.put("区" + region, volMap.get("区" + region).add(volume));
        }

        // VWAP计算
        for (int i = 1; i <= 6; i++) {
            BigDecimal totalVol = volMap.get("区" + i);
            if (totalVol.compareTo(BigDecimal.ZERO) > 0) {
                costMap.put("区" + i, costMap.get("区" + i).divide(totalVol, 6, RoundingMode.HALF_UP));
            } else {
                costMap.put("区" + i, BigDecimal.ZERO);
            }
        }

        // 定义区间和方向
        String[][] regions = {
                {"1", high.toPlainString(), "∞", "buy"},
                {"2", midHigh.toPlainString(), high.toPlainString(), "sell"},
                {"3", mid.toPlainString(), midHigh.toPlainString(), "buy"},
                {"4", midLow.toPlainString(), mid.toPlainString(), "sell"},
                {"5", low.toPlainString(), midLow.toPlainString(), "buy"},
                {"6", "-∞", low.toPlainString(), "sell"}
        };

        for (String[] r : regions) {
            String regionNum = r[0];
            String start = r[1];
            String end = r[2];
            String direction = r[3];

            boolean isCurrent = false;
            BigDecimal startVal = start.equals("-∞") ? null : new BigDecimal(start);
            BigDecimal endVal = end.equals("∞") ? null : new BigDecimal(end);

            if ((startVal == null || price.compareTo(startVal) > 0) &&
                    (endVal == null || price.compareTo(endVal) <= 0)) {
                isCurrent = true;
            }

            log.info("区域 " + regionNum + "（" + start + " ~ " + end + "），方向：" + direction +
                    "，成本：" + costMap.get("区" + regionNum) +
                    (isCurrent ? " ← 当前价格" : ""));
        }

        // ⭐⭐ 新增：返回每个区间的成本
        return costMap;
    }





}
